package Controller

import (
	"back_go/DAO"
	models "back_go/DAO/model"
	middleware "back_go/Middleware"
	"back_go/Response"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/patrickmn/go-cache"
	"math"
	"net/http"
	"strconv"
	"time"
)

type Role struct {
	RoleId     int       `json:"roleId"`
	RoleName   string    `json:"roleName"`
	Remark     string    `json:"remark"`
	MenuIdList []int     `json:"menuIdList"`
	CreateTime time.Time `json:"createTime"`
}

// SaveRole 新增角色菜单
/*
    参数：
	roleName: 角色名称
	remark: 备注
	menuIdList: 菜单id集合
	token: token
	返回：
		Response.ResponseBody    响应体
*/
func SaveRole(c *gin.Context) {
	var engine = DAO.Engine
	var role Role
	err := c.BindJSON(&role)
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "A00014",
			Msg:       "方法参数没有校验",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
			Fail:      false,
		})
		return
	}
	var sysRole models.TzSysRole
	sysRole.RoleName = role.RoleName
	sysRole.Remark = role.Remark
	sysRole.CreateTime = time.Now()
	session := engine.NewSession()
	defer session.Close()

	// 开启事务
	err = session.Begin()

	_, _ = session.Insert(&sysRole)
	RoleId := sysRole.RoleId

	for _, v := range role.MenuIdList {
		var sysRoleMenu models.TzSysRoleMenu
		sysRoleMenu.RoleId = RoleId
		sysRoleMenu.MenuId = int64(v)
		_, _ = session.Insert(&sysRoleMenu)
	}
	if err != nil {
		// 事务回滚
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "A00014",
			Msg:       "新增角色失败",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		_ = session.Rollback()
		// 处理错误
		return
	}
	err = session.Commit()

	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       "ok",
		Data:      nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Success:   true,
		Fail:      false,
	})
	return
}

// ChangeRole 更新角色菜单
/*
    参数：
	roleName: 角色名称
	remark: 备注
	menuIdList: 菜单id集合
	token: token
	返回：
		Response.ResponseBody    响应体
*/
//goland:noinspection Annotator
func ChangeRole(c *gin.Context) {
	var engine = DAO.Engine
	var role Role
	err := c.BindJSON(&role)
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "A00014",
			Msg:       "方法参数没有校验",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
			Fail:      false,
		})
		return
	}
	var sysRole models.TzSysRole
	sysRole.RoleName = role.RoleName
	sysRole.Remark = role.Remark
	sysRole.CreateTime = time.Now()
	session := engine.NewSession()
	defer session.Close()

	fmt.Println(role.RoleId)
	// 开启事务
	err = session.Begin()

	// 删除之前的角色菜单
	//goland:noinspection ALL
	sql := "delete from tz_sys_role where role_id = " + strconv.FormatInt(int64(role.RoleId), 10)
	_, _ = session.Exec(sql)
	//goland:noinspection ALL,Annotator
	sql = "delete from tz_sys_role_menu where role_id = " + strconv.FormatInt(int64(role.RoleId), 10)
	_, _ = session.Exec(sql)

	_, _ = session.Insert(&sysRole)
	var RoleId = sysRole.RoleId
	for _, v := range role.MenuIdList {
		var sysRoleMenu models.TzSysRoleMenu
		sysRoleMenu.RoleId = RoleId
		sysRoleMenu.MenuId = int64(v)
		_, _ = session.Insert(&sysRoleMenu)
	}

	if err != nil {
		// 事务回滚
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "A00014",
			Msg:       "更新角色失败",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		_ = session.Rollback()
		// 处理错误
		return
	}

	err = session.Commit()

	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       "ok",
		Data:      nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Success:   true,
		Fail:      false,
	})
	return
}

// DelRoleById 删除角色菜单
/*
   参数:
	roleId: 角色id集合
	token: token
	返回：
		Response.ResponseBody    响应体
*/
func DelRoleById(c *gin.Context) {
	var engine = DAO.Engine
	var RoleId []int
	err := c.ShouldBindJSON(&RoleId)
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "删除角色失败",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	for i := range RoleId {

		_, err := engine.Where("role_id = ?", RoleId[i]).Delete(&models.TzSysRole{})
		_, err1 := engine.Where("role_id = ?", RoleId[i]).Delete(&models.TzSysRoleMenu{})
		if err != nil || err1 != nil {
			c.JSON(http.StatusOK, Response.ResponseBody{
				Code:      "00000",
				Msg:       "删除角色失败",
				Data:      nil,
				Version:   "1.0",
				Timestamp: time.Now().Unix(),
				Sign:      "",
				Success:   true,
			})
			return
		}
	}
	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       "ok",
		Data:      nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Success:   true,
		Fail:      false,
	})
}

type Records struct {
	RoleId     int     `json:"roleId"`
	RoleName   string  `json:"roleName"`
	Remark     string  `json:"remark"`
	MenuIdList []int64 `json:"menuIdList"`
	CreateTime string  `json:"createTime"`
}

// PageParam1 是一个泛型结构体，用于封装分页查询的相关参数和结果
type PageParam1[T any] struct {
	// Current 表示当前页码，类型为 interface{}，可存储任意类型数据
	Current interface{} `json:"current"`
	// Size 表示每页显示的记录数量，类型为 interface{}，可存储任意类型数据
	Size interface{} `json:"size"`
	// Records 表示当前页的记录列表，类型为 interface{}，可存储任意类型数据
	Records interface{} `json:"records"`
	// Total 表示所有记录的总数，类型为 interface{}，可存储任意类型数据
	Total interface{} `json:"total"`
	// Pages 表示总页数，类型为 int
	Pages int `json:"pages"`
}

// GetRolePage 获取角色列表
/*
    参数：
		roleName: 角色名称
		size: 分页大小
	    current: 分页当前页
		token: token
	返回：
		Response.ResponseBody    响应体
*/
func GetRolePage(c *gin.Context) {

	var engine = DAO.Engine

	RoleName := c.Query("roleName")
	Size := c.Query("size")
	Current := c.Query("current")

	if Size == "" {
		Size = "10"
	} else {
		size, err := strconv.Atoi(Size)
		if err != nil || size <= 0 {
			Size = "10"
		}
	}

	if Current == "" {
		Current = "1"
	} else {
		current, err := strconv.Atoi(Current)
		if err != nil || current <= 0 {
			Current = "1"
		}
	}

	pageSize, _ := strconv.Atoi(Size)
	pageCurrent, _ := strconv.Atoi(Current)
	var sysRole []models.TzSysRole
	_ = engine.Where("role_name like?", "%"+RoleName+"%").Limit(pageSize, pageCurrent-1).Find(&sysRole)

	var records []Records
	for i := range sysRole {
		var record Records
		record.RoleId = int(sysRole[i].RoleId)
		record.RoleName = sysRole[i].RoleName
		record.Remark = sysRole[i].Remark
		record.CreateTime = sysRole[i].CreateTime.Format("2006-01-02 15:04:05")
		record.MenuIdList = nil
		records = append(records, record)
	}

	var Role models.TzSysRole
	count, _ := engine.Where("role_name like?", "%"+RoleName+"%").Count(Role)
	c.JSON(200, Response.ResponseBody{
		Code: "00000",
		Msg:  "ok",
		Data: PageParam1[Records]{
			Current: Current,
			Size:    Size,
			Records: records,
			Total:   count,
			Pages:   int(math.Ceil(float64(count) / float64(pageSize))),
		},
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Success:   true,
	})

}

// GetRoleList 获取角色列表
/*
	参数：
		token: token
	返回：
		Response.ResponseBody    响应体
*/
func GetRoleList(c *gin.Context) {
	// 创建缓存对象

	// 尝试从缓存中获取角色列表
	if cachedData, found := middleware.Cacher.Get("GetRoleList"); found {
		c.JSON(200, Response.ResponseBody{
			Code:      "00000",
			Msg:       "ok",
			Data:      cachedData,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Success:   true,
		})
		return
	}

	var engine = DAO.Engine
	var records []Records
	var sysRole []models.TzSysRole
	_ = engine.Find(&sysRole)
	for _, role := range sysRole {
		record := Records{
			RoleId:     int(role.RoleId),
			RoleName:   role.RoleName,
			Remark:     role.Remark,
			CreateTime: role.CreateTime.Format("2006-01-02 15:04:05"),
		}

		var RoleMenu []models.TzSysRoleMenu
		_ = engine.Where("role_id =?", role.RoleId).Find(&RoleMenu)
		for _, v := range RoleMenu {
			record.MenuIdList = append(record.MenuIdList, v.MenuId)
		}

		records = append(records, record)
	}

	// 将角色列表存入缓存
	middleware.Cacher.Set("GetRoleList", records, cache.DefaultExpiration)

	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "ok",
		Data:      records,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Success:   true,
	})
}

// GetRoleInfoById 获取角色信息
/*
	参数：
		roleId: 角色id
		token: token
	返回：
		Response.ResponseBody    响应体
*/
func GetRoleInfoById(c *gin.Context) {
	var engine = DAO.Engine
	var roleId = c.Param("roleId")

	var sysRole models.TzSysRole
	_, _ = engine.Where("role_id=?", roleId).Get(&sysRole)
	var records Records
	records.RoleId = int(sysRole.RoleId)
	records.RoleName = sysRole.RoleName
	records.Remark = sysRole.Remark
	records.CreateTime = sysRole.CreateTime.Format("2006-01-02 15:04:05")
	var RoleMenu []models.TzSysRoleMenu
	_ = engine.Where("role_id =?", roleId).Find(&RoleMenu)
	for _, v := range RoleMenu {
		records.MenuIdList = append(records.MenuIdList, v.MenuId)
	}
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "ok",
		Data:      records,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Success:   true,
	})
}
